using System;
using System.Collections.Generic;
using System.Text;
using T.FAS.Runtime.Base.Common;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.ScheduleJob.SPI;
using T.ServiceComponent.Cluster.Client;
using T.ServiceComponent.Kernel.Service;
using T.ServiceComponent.Monitor.Client;

namespace T.FAS.Runtime.ScheduleJob.Engine
{
    public class ScheduleJobExecuteEngine : IScheduleJobExecuteEngine
    {
        protected IScheduleJobExecuteHandler executeHandler;
        public void Execute(ScheduleJobExecContext context)
        {
            var operName = "JobEngine_Execute";
            FASContextHelper.GetInstance().InitRpcContextWithSub();
            //编排控制

            TResult dataResult = null;
            var start = DateTime.Now;
            Exception ex = null;
            try
            {
                Base.Common.LogUtil.Log(context.ScheduleJobID, "ScheduleJob");
                var proxy = ScheduleJobImpEngineFactory.Create(context);

                InitSchedulJobImpExecuteHandler(proxy);

                BeforeExecute(context);

                var result = proxy.Execute(context);

                AfterExecute(context, dataResult);

            }
            catch (Exception e)
            {
                ex = e;
                Base.Common.LogUtil.Log(e.ToString(), "ScheduleJob");
                //NoticeHelper.SendMsgToDingDing(context.ScheduleJobMetaData.Creator, context.ScheduleJobID + "执行失败");
                ScheduleJobEngineMonitor.RootCaseReport(operName, start, context, ex);
                ExecuteError(context,ex);
                throw new FasException(ScheduleJobRTPExceptionCode.ScheduleJobExecuteError, ex.Message, ex);
            }
            finally
            {
                //TODO上报监控和日志
                ScheduleJobEngineMonitor.Trace(operName, start, context, ex);
                ScheduleJobEngineMonitor.MointorRTPEngineInvokeTotalTPS(context);
                if (ex == null)
                {
                    ScheduleJobEngineMonitor.MointorRTPEngineInvokeSuccessTPS(context);
                    ScheduleJobEngineMonitor.MointorRTPEngineInvokeSuccessDuration(context, (DateTime.Now - start).TotalMilliseconds);
                }
                else
                {
                    ScheduleJobEngineMonitor.MointorRTPEngineInvokeFailTPS(context);
                }
            }

        }

        private void ExecuteError(ScheduleJobExecContext context, Exception ex)
        {
            return;
        }

        private void AfterExecute(ScheduleJobExecContext context, TResult dataResult)
        {
            if (executeHandler != null)
                executeHandler.AfterExecute(context,dataResult);
        }

        private void BeforeExecute(ScheduleJobExecContext context)
        {
            if (executeHandler != null)
                executeHandler.BeforeExecute(context);
        }

        private void InitSchedulJobImpExecuteHandler(IScheduleJobImpEngineProxy proxy)
        {
            executeHandler = proxy as IScheduleJobExecuteHandler;
        }
        protected TResult ConstructSubscriptionDataResult(IScheduleJobImpEngineProxy proxy,ScheduleJobExecContext context, object result)
        {
            var builder = proxy as IScheduleJobDataResultBuilder;

            return builder.BuildScheduleJobDataResult(context, result);
        }

    }
}
